/******************************************************************************
 * FILE:			ADT_L0_VxWorks.c
 *
 * Copyright (c) 2007-2012, Alta Data Technologies LLC (ADT), All Rights Reserved.
 * Use of this software is subject to the ADT Software License (latest
 * revision), US Government or local laws and the ADT Terms and Conditions 
 * of Sale (latest revision).
 *
 * DESCRIPTION:
 *	Source file for VxWorks Layer 0 API.
 *	
 *****************************************************************************/
/*! \file ADT_L0_VxWorks.c 
 *  \brief Source file for the ADT Layer 0 API (for VxWorks 5.5 & 6.x)
 *
 *  This file contains all the VxWorks specific low-level code.
 *  This configuration has proven to be the most universal. 
 *  See ADT_L0_VxWorks_readme.txt for more information on porting to 
 *  different systems.
 *
 *  YOU MAY NEED TO MODIFY THIS FILE TO WORK WITH YOUR SPECIFIC BSP!
 */

#include <vxWorks.h>
#include <cacheLib.h> 
#include <sockLib.h> 
#include "inetLib.h" 
#include "intLib.h" 
#include "iv.h"
#include "taskLib.h"
#include "sysLib.h"
#include "tickLib.h"
#include "selectLib.h"
#include "time.h"
#include "timers.h"
#include "drv/pci/pciConfigLib.h"
#include "drv/pci/pciIntLib.h"
#include "logLib.h"
#include "stdlib.h"
#include "sys/mman.h"
#include "stdio.h"
#include "ADT_L0.h"

/* Define X86_PLATFORM if on an x86 system, otherwise comment the next line out */
#define X86_PLATFORM

/* Byte and Word Swapping Macros */
#ifdef X86_PLATFORM
IMPORT UINT8 *sysInumTbl;
/* FOR X86 (little endian) system */
#define BS32(v) v
#define BS16(v) v
#else
/* FOR PPC (big endian) systems */
#define BS32(v) (((v & 0xFF) << 24) | ((v & 0xFF00) << 8) | ((v >> 8) & 0xFF00) | ((v >> 24) & 0xFF))
#define BS16(v) ((v & 0xFF) << 8) | ((v >> 8) & 0xFF)
#endif

typedef int SOCKET;

/* Internal type used for linked-list of devices enabled for interrupts */
typedef struct adt_int_node {
	ADT_L0_UINT32 DevID;
	ADT_L0_UINT32 ChanRegOffset;
	void (ADT_L0_CALL_CONV *pUser_Function)(void *);
	void *pUserData;
	struct adt_int_node * pNext;
} ADT_INT_NODE;

/* Internal type used for linked-list of ENET device information */
typedef struct adt_enet_node {
	ADT_L0_UINT32 DevID;
	SOCKET        eNET_Socket;
	ADT_L0_UINT32 eNET_ServerIPaddr;
	ADT_L0_UINT32 eNET_ClientIPaddr;
	ADT_L0_UINT16 eNET_ClientUdpPort;
	ADT_L0_UINT32 eNET_SequenceNumber;
	ADT_L0_UINT32 eNET_TransactionCount;	/* Number of ADCP transactions */
	ADT_L0_UINT32 eNET_RetryCount;			/* Number of ADCP retries */
	ADT_L0_UINT32 eNET_FailureCount;		/* Number of ADCP failures (all retries failed) */
	struct adt_enet_node * pNext;
    SEM_ID        eNET_Mutex;
} ADT_ENET_NODE;

/* Global internal pointer - head ptr for interrupt linked list */
ADT_INT_NODE * pHead_IntList = NULL;

/* Global internal array of pointers for SIMULATED devices */
ADT_L0_UINT32 initedInternalArrays = 0;
/* (SIMULATED backplane type), (SIMULATED board type), board #, channel type, channel # (max 4 channels) */
ADT_L0_UINT32 *SimDevMemory[16][256][4];  

/* Global internal array of counters for number of channels initialized for each board */
ADT_L0_UINT32 channelInitCount[16][256][16];  /* Backplane type, board type, board # */

/* Global internal arrays of base memory pointers for BAR0 and BAR2, interrupt line */
ADT_L0_UINT32 memoryBase0[16][256][16];  /* Backplane type, board type, board # */
ADT_L0_UINT32 memoryBase2[16][256][16];  /* Backplane type, board type, board # */
ADT_L0_UINT8 intLine[16][256][16];  /* Backplane type, board type, board # */

int ADT_Intr_cnt = 0;
int ADT_DMA_Intr = 0;

enum PLX_M_REGS {
    /* DMA registers */
    PLX_M_PCICR    = 0x04,  /* PCI Command Register */
    PLX_M_MARBR    = 0x08,  /* Mode/DMA Arbitration Register */
    PLX_M_BIGEND   = 0x0C,  /* Big/Little Endian Descriptor */
    PLX_M_LMISC1   = 0x0D,  /* Local Misc Control */
    PLX_M_INTCSR   = 0x68,  /* INT CSR */
    PLX_M_DMAMODE0 = 0x80,  /* DMA Channel 0 Mode */
    PLX_M_DMAPADR0 = 0x84,  /* DMA Channel 0 PCI Address */
    PLX_M_DMALADR0 = 0x88,  /* DMA Channel 0 Local Address */
    PLX_M_DMASIZ0  = 0x8C,  /* DMA Channel 0 Transfer Size (bytes) */
    PLX_M_DMADPR0  = 0x90,  /* DMA Channel 0 Descriptor Pointer */
    PLX_M_DMAMODE1 = 0x94,  /* DMA Channel 1 Mode */
    PLX_M_DMAPADR1 = 0x98,  /* DMA Channel 1 PCI Address */
    PLX_M_DMALADR1 = 0x9C,  /* DMA Channel 1 Local Address */
    PLX_M_DMASIZ1  = 0xA0,  /* DMA Channel 1 Transfer Size (bytes) */
    PLX_M_DMADPR1  = 0xA4,  /* DMA Channel 1 Descriptor Pointer */
    PLX_M_DMACSR0  = 0xA8,  /* DMA Channel 0 Command/Status */
    PLX_M_DMACSR1  = 0xA9,  /* DMA Channel 1 Command/Status */
};

enum 
{
    BIT0  = 0x00000001, BIT1  = 0x00000002, BIT2  = 0x00000004, BIT3  = 0x00000008,
    BIT4  = 0x00000010, BIT5  = 0x00000020, BIT6  = 0x00000040, BIT7  = 0x00000080,
    BIT8  = 0x00000100, BIT9  = 0x00000200, BIT10 = 0x00000400, BIT11 = 0x00000800,
    BIT12 = 0x00001000, BIT13 = 0x00002000, BIT14 = 0x00004000, BIT15 = 0x00008000,
    BIT16 = 0x00010000, BIT17 = 0x00020000, BIT18 = 0x00040000, BIT19 = 0x00080000,
    BIT20 = 0x00100000, BIT21 = 0x00200000, BIT22 = 0x00400000, BIT23 = 0x00800000,
    BIT24 = 0x01000000, BIT25 = 0x02000000, BIT26 = 0x04000000, BIT27 = 0x08000000,
    BIT28 = 0x10000000, BIT29 = 0x20000000, BIT30 = 0x40000000,
    BIT31 = (int)0x80000000
};

/* ENET devices need to associate the DEVID to an IP ADDRESS */
ADT_L0_UINT32 eNET_isRunning = 0;   /* Flag used to indicate if eNET services are running */
ADT_L0_UINT32 eNET_count = 0;       /* Count of open ENET devices */
ADT_ENET_NODE *pENET_Head = NULL;	/* Pointer to head of linked list of ENET device info records */

/* Prototypes for internal functions */
ADT_L0_UINT32 ADT_L0_CALL_CONV Internal_GetChannelRegOffset(ADT_L0_UINT32 devID, ADT_L0_UINT32 *pChannel, ADT_L0_UINT32 *pChannelRegOffset);
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_Internal_eNet_Start();
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_Internal_eNet_Stop();
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_Internal_eNet_ADCP_Execute(ADT_L0_UINT32 devID, ADT_L0_ADCP_UDPPAYLOAD *command, ADT_L0_ADCP_UDPPAYLOAD *response);
ADT_ENET_NODE * ADT_L0_Internal_Find_ENET_Node(ADT_L0_UINT32 devID);
ADT_ENET_NODE * ADT_L0_Internal_FindOrAdd_ENET_Node(ADT_L0_UINT32 devID);
void ADT_L0_Internal_Destroy_ENET_Node(ADT_L0_UINT32 devID);

#ifdef __cplusplus
extern "C" {
#endif

/******************************************************************************
  FUNCTION:		ADT_L0_msSleep
 *****************************************************************************/
/*! \brief Waits for the requested number of milliseconds
 *
 * This function waits for the requested number of milliseconds.
 *
 * @param msDelay is the number of milliseconds to wait.
*/
void ADT_L0_CALL_CONV ADT_L0_msSleep(ADT_L0_UINT32 msDelay)
{
	static int delayLoop = 0;
	int ix;
	int iy;
	int maxLoop;
	int start;
	int stop;
	int mpt; /* microsecs per tick */

	msDelay = msDelay*1000; /* Convert input to usec*/

	if (delayLoop == 0 || msDelay == 0xffffffff) /* need calibration? Run first time only when delayLoop=0 */
	{
		start = 0;
		stop = 0;
		mpt = (1000 * 1000) / sysClkRateGet (); /* microsecs per tick */
   
		for (delayLoop = 1; delayLoop < 0x1000 && stop == start; delayLoop<<=1)
		{
			for (stop = start = tickGet (); start == stop; start = tickGet ())
				; /* wait for clock turn over */
   
			ADT_L0_msSleep(mpt/1000); /* single recursion */
			stop = tickGet ();
		}

		maxLoop = delayLoop / 2; /* loop above overshoots */

		start = 0;
		stop = 0;
		if (delayLoop < 4)
			delayLoop = 4;
   
		for (delayLoop /= 4; delayLoop<maxLoop && stop == start; delayLoop++)
		{
			for (stop = start = tickGet (); start == stop; start = tickGet ())
				; /* wait for clock turn over */
   
			ADT_L0_msSleep(mpt/1000); /* single recursion */
			stop = tickGet ();
		}
	}

	/* Main delay loop after calibration above*/
	for (iy = 0; iy < msDelay; iy++)
	{
		for (ix = 0; ix < delayLoop; ix++);
	}
}

/******************************************************************************
  FUNCTION:		ADT_L0_MapMemory
 *****************************************************************************/
/*! \brief Maps memory
 *
 * This function maps the requested amount of memory and stores the memory
 * pointer internally for use with the memory read/write functions.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
*/
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_MapMemory(ADT_L0_UINT32 devID, ADT_L0_UINT32 startupOptions, ADT_L0_UINT32 ClientIpAddress, ADT_L0_UINT32 ServerIpAddress) {
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum, i, temp;
	ADT_L0_UINT32 instance, membase0, membase2, u32DMAMODE;
	int pciBus, pciDevice, pciFunc;
	ADT_ENET_NODE *pENET_Node = NULL;
	int bind_rslt;
	struct sockaddr_in client_addrinfo;
	int sd;
	
	/* On first call to this function . . . */
	if (initedInternalArrays == 0) {
		/* Init the SimDevMemory array to all NULL ptrs */

		memset(SimDevMemory, 0, sizeof(SimDevMemory));

		/* Init the channel init count per board to all ZERO */
		memset(channelInitCount, 0, sizeof(channelInitCount));

		/* Init the memory base pointers to all ZERO */
		memset(memoryBase0, 0, sizeof(memoryBase0));
		memset(memoryBase2, 0, sizeof(memoryBase2));

		initedInternalArrays = 1;
	}

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
	case ADT_DEVID_BACKPLANETYPE_PCI:
		/* Only perform the mapping if we have not already mapped this board */
	    if (channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16] == 0)  
		{  
	    	/***** VXWORKS MEM MAPPING CODE *****/
	    	/* Find the PCI device based on board type */
	    	instance = boardNum >> 16;
	    	if (boardType == ADT_DEVID_BOARDTYPE_PMC1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMC1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PMC-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PMC-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PC104P1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PC104P1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PC104P-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PC104P-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCI1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCI1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCI-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCI-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCCD1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCCD1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCCD-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCCD-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCI104E1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCI104E1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCI104E-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCI104E-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_XMC1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_XMC1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT XMC-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT XMC-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_ECD54_1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_ECD54_1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT ECD54-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT ECD54-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCIE4L1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE4L1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCIE4L-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCIE4L-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCIE1L1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE1L1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCIE1L-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCIE1L-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_MPCIE1553) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_MPCIE1553, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT MPCIE1553-1553 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT MPCIE1553-1553 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PMCA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMCA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PMC-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PMC-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PC104PA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PC104PA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PC104P-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PC104P-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCIA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCI-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCI-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCCDA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCCDA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCCD-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCCD-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCI104EA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCI104EA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCI104E-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCI104E-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_XMCA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_XMCA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT XMC-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT XMC-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_ECD54_A429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_ECD54_A429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT ECD54-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT ECD54-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCIE4LA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE4LA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCIE4L-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCIE4L-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PCIE1LA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE1LA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PCIE1L-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PCIE1L-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_MPCIEA429) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_MPCIEA429, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT MPCIE-A429 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT MPCIE-A429 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PMCMA4) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMCMA4, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PMC-MA4 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PMC-MA4 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PC104EMA4) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PC104EMA4, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PC104E-MA4 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PC104E-MA4 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_XMCMA4) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_XMCMA4, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT XMC-MA4 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT XMC-MA4 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PMCWMUX) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMCWMUX, instance, &pciBus, &pciDevice, &pciFunc) == OK)
	    		{
	    			logMsg("ADT PMC-WMUX found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PMC-WMUX NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
	    	else {
	    		result = ADT_ERR_UNSUPPORTED_BOARDTYPE;
	    	}

	    	/* Get the memory mapped base addresses for BAR0 and BAR2 */
	    	/* THIS IS USUALLY THE KEY AREA FOR DIFFERENT VXWORKS SYSTEMS/BSPs */
	    	if (result == ADT_SUCCESS) {
	    		pciConfigInLong(pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_0, &membase0);
	    		pciConfigInLong(pciBus, pciDevice, pciFunc, PCI_CFG_BASE_ADDRESS_2, &membase2);
	    		/* This memoryBase assignments can change with different systems - see VxWorks_readme.txt */
	    		memoryBase0[backplaneType >> 28][boardType >> 20][boardNum >> 16] = membase0;
	    		memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16] = membase2;
	    		/* Get Interrupt line on the Client PCI card */
	    		pciConfigInByte(pciBus, pciDevice, pciFunc,
	    				PCI_CFG_DEV_INT_LINE, 		/* offset into the configuration space */
	    				&intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16]);  /* data read from the offset */
									
	    	}	
		}
	/*************************************************************************/
	break;

	case ADT_DEVID_BACKPLANETYPE_SIMULATED:
		if (boardType == ADT_DEVID_BOARDTYPE_SIM1553) 
		{
			if (channelNum < 4) {  /* max 4 channels on sim 1553 device */
				if ( SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] == NULL) {
					/* Allocate 5 channels of memory for the board for each channel 
					 * This requires that all memory offsets change from BOARD offsets to CHANNEL offsets.
					 */
					SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] = (ADT_L0_UINT32 *) malloc(ADT_MEMSIZE_SIM1553_CHAN * 5);
					if (SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] != NULL) {
						/* Clear memory */
						for (i=0; i<ADT_MEMSIZE_SIM1553_CHAN*5/4; i++) 
							SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][i] = 0;

						/* Set config register */
						SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][0x44 / 4] = 0x00008E0F;

						/* Set PE Status register to enable SC */
						SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][((ADT_MEMSIZE_SIM1553_CHAN * (channelNum + 1)) + 4) / 4] = 0x08000000;

					}
					else result = ADT_FAILURE;
				}
			}
			else result = ADT_ERR_INVALID_CHANNEL_NUM;
		break;
		}
		else if (boardType == ADT_DEVID_BOARDTYPE_SIMA429) 
		{
			if (channelNum < 4) {  /* max 4 channels on sim A429 device */
				if ( SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] == NULL) {
					/* Allocate 5 channels of memory for the board for each channel 
					 * This requires that all memory offsets change from BOARD offsets to CHANNEL offsets.
					 */
					SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] = (ADT_L0_UINT32 *) malloc(ADT_MEMSIZE_SIMA429_CHAN * 3);
					if (SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] != NULL) {
						/* Clear memory */
						for (i=0; i<ADT_MEMSIZE_SIMA429_CHAN*3/4; i++) 
							SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][i] = 0;
						/* Set config register */
						SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][0x44 / 4] = 0x03008A00;

						/* Set PE Status register to enable SC */
						SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][((ADT_MEMSIZE_SIMA429_CHAN * (channelNum + 1)) + 0x04) / 4] = 0x08000000;

						/* Set PE TX-RX channel configuration for 8 TX and 16 RX channels */
						SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][((ADT_MEMSIZE_SIMA429_CHAN * (channelNum + 1)) + 0x0C) / 4] = 0x00FFFFFF;

					}
					else result = ADT_FAILURE;
				}
			}
			else result = ADT_ERR_INVALID_CHANNEL_NUM;
			break;
		}
		else result = ADT_ERR_UNSUPPORTED_BACKPLANE;
		break;

	case ADT_DEVID_BACKPLANETYPE_ENET:
		/* Start socket services (if not already running) */
		if (!eNET_isRunning) result = ADT_L0_Internal_eNet_Start();

		/* Find or add an ENET Device Information node for the DEVID */
		pENET_Node = ADT_L0_Internal_FindOrAdd_ENET_Node(devID);
		if (pENET_Node != NULL)
		{
			/* Store Server and Client IP addresses for later use in building packets */
			pENET_Node->eNET_ServerIPaddr = ServerIpAddress;
			pENET_Node->eNET_ClientIPaddr = ClientIpAddress;

			/* Clear the ENET statistices for the device */
			pENET_Node->eNET_TransactionCount = 0;
			pENET_Node->eNET_RetryCount = 0;
			pENET_Node->eNET_FailureCount = 0;

			/* Create a socket for the device */
			pENET_Node->eNET_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
			memset(&client_addrinfo, 0, sizeof(client_addrinfo));
			client_addrinfo.sin_family = AF_INET;
			client_addrinfo.sin_port = htons(0);
				
			client_addrinfo.sin_addr.s_addr = htonl(pENET_Node->eNET_ClientIPaddr);

			pENET_Node->eNET_ClientUdpPort = ADT_L0_ENET_ADCP_CLIENT_PORT_START - 1;
			bind_rslt = -1;
	/*		printf("Client = %08X, Server = %08X",ClientIpAddress, ServerIpAddress);*/
			/* Find and bind an available client port number from 55513 to 56511 */
			while ((bind_rslt != 0) && (pENET_Node->eNET_ClientUdpPort <= ADT_L0_ENET_ADCP_CLIENT_PORT_END)) {
				pENET_Node->eNET_ClientUdpPort++;
				client_addrinfo.sin_port = htons(pENET_Node->eNET_ClientUdpPort);

				sd = pENET_Node->eNET_Socket;
				bind_rslt = bind(sd, (struct sockaddr *) &client_addrinfo, sizeof(client_addrinfo));
			}
			if (pENET_Node->eNET_ClientUdpPort > ADT_L0_ENET_ADCP_CLIENT_PORT_END) result = ADT_ERR_ENET_NO_PORT_AVAILABLE;  /* No port available */
				
			if (result == ADT_SUCCESS) 
			{
				/* Ping the ENET device by reading the GLOBAL device ALIGN CHECK WORD (at byte offset 0x4C).
				   This should be 0x12345678.  If we get anything else return ADT_ERR_ENET_READ_FAIL. */
				result = ADT_L0_ReadMem32(devID, 0x4C, &temp, 1);
				if (result == ADT_SUCCESS) {
					if (temp != 0x12345678) result = ADT_ERR_ENET_READ_FAIL;
					else eNET_count++;
				}
			}
			else  /* If not successful, release the socket descriptor */
			{
				close(pENET_Node->eNET_Socket);
				pENET_Node->eNET_Socket = (SOCKET) NULL;
				ADT_L0_Internal_Destroy_ENET_Node(devID);
			}
		}
		else result = ADT_FAILURE; /* could not find/add node for ENET device information */

		break;

	default:
		result = ADT_ERR_UNSUPPORTED_BACKPLANE;
		break;
	}

	if (result == ADT_SUCCESS) {
		channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16]++;

		/* Perform the appropriate action to enable interrupts based on board type */
		switch (boardType) {
			case ADT_DEVID_BOARDTYPE_PMC1553:
			case ADT_DEVID_BOARDTYPE_PC104P1553:
			case ADT_DEVID_BOARDTYPE_PCI1553:
			case ADT_DEVID_BOARDTYPE_TESTA429:
			case ADT_DEVID_BOARDTYPE_PMCA429:
			case ADT_DEVID_BOARDTYPE_PC104PA429:
			case ADT_DEVID_BOARDTYPE_PCIA429:
			case ADT_DEVID_BOARDTYPE_PMCMA4:
			case ADT_DEVID_BOARDTYPE_PMCWMUX:
				/* Enable interrupt in PLX9056 */
				temp = 0;
				result = ADT_L0_ReadSetupMem32(devID, PLX_M_INTCSR, &temp, 1);
				temp |= BIT11 | BIT18;
				result = ADT_L0_WriteSetupMem32(devID, PLX_M_INTCSR, &temp, 1);

				/* Clear the compliance bit in the PLX9056 to enable "Direct Slave Retry Delay Clocks"
				   feature.  A PCI Retry will not be issued until after 32 PCI clocks (9056 default) 
				   from the beginning of a Direct Slave Read Access */
				temp = 0;
				result = ADT_L0_ReadSetupMem32(devID, PLX_M_MARBR, &temp, 1);
				temp &= ~0x01000000;
				result = ADT_L0_WriteSetupMem32(devID, PLX_M_MARBR, &temp, 1);

				/* Write to BAR0 memory and PLX offsets */
	            /* Use common settings for chain and direct DMA */
				u32DMAMODE = BIT6  /* Enable Ready input */
#if 0
				|    BIT10         /* Interrupt Enable */
	            |    BIT17         /* Interrupt Select */
#endif
	            |   (BIT1 | BIT0); /* 32-bit */
				ADT_L0_WriteSetupMem32(devID,PLX_M_DMAMODE0, &u32DMAMODE, 1); /*offset 0x80*/

				temp = (UINT32)0x8;/* Force direction to read from local bus */	
				ADT_L0_WriteSetupMem32(devID,PLX_M_DMADPR0, &temp, 1);/* offset 0x90 */

				/* Set DMA Big-Endian data for PPC */
				temp = BIT7;
				ADT_L0_WriteSetupMem32(devID,PLX_M_BIGEND, &temp, 1);/* offset 0x0C */
				break;

			default:
				break;
		}
	}
	return( result );
}

/******************************************************************************
  FUNCTION:		ADT_L0_MapMemory_pciInfo
 *****************************************************************************/
/*! \brief Maps memory
 *
 * This function maps the requested amount of memory and stores the memory
 * pointer internally for use with the memory read/write functions.
 * Also returns PCI info - Bus, Device, Function.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
*/
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_MapMemory_pciInfo(ADT_L0_UINT32 devID, ADT_L0_UINT32 startupOptions, ADT_L0_UINT32 *pciBus, ADT_L0_UINT32 *pciDevice, ADT_L0_UINT32 *pciFunc) {
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum, temp;
	ADT_L0_UINT32 instance, membase0, membase2, u32DMAMODE;
	
	/* On first call to this function . . . */
	if (initedInternalArrays == 0) {
		/* Init the SimDevMemory array to all NULL ptrs */
		memset(SimDevMemory, 0, sizeof(SimDevMemory));

		/* Init the channel init count per board to all ZERO */
		memset(channelInitCount, 0, sizeof(channelInitCount));

		/* Init the memory base pointers to all ZERO */
		memset(memoryBase0, 0, sizeof(memoryBase0));
		memset(memoryBase2, 0, sizeof(memoryBase2));

		initedInternalArrays = 1;
	}

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Only perform the mapping if we have not already mapped this board */
	if (channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16] == 0) 
	{
		/* Perform the appropriate action based on BACKPLANE TYPE */
		switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
			/***** VXWORKS MEM MAPPING CODE *****/
			/* Find the PCI device based on board type */
			instance = boardNum >> 16;
			if (boardType == ADT_DEVID_BOARDTYPE_PMC1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMC1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PMC-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PMC-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PC104P1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PC104P1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PC104P-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PC104P-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCI1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCI1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCI-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCI-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCCD1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCCD1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCCD-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCCD-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCI104E1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCI104E1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCI104E-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCI104E-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_XMC1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_XMC1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT XMC-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT XMC-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_ECD54_1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_ECD54_1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT ECD54-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT ECD54-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCIE4L1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE4L1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCIE4L-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCIE4L-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCIE1L1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE1L1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCIE1L-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCIE1L-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_MPCIE1553) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_MPCIE1553, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT MPCIE1553-1553 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT MPCIE1553-1553 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PMCA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMCA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PMC-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PMC-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PC104PA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PC104PA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PC104P-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PC104P-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCIA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCI-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCI-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCCDA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCCDA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCCD-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCCD-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCI104EA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCI104EA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCI104E-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCI104E-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_XMCA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_XMCA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT XMC-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT XMC-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_ECD54_A429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_ECD54_A429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT ECD54-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT ECD54-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCIE4LA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE4LA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCIE4L-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCIE4L-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PCIE1LA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PCIE1LA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PCIE1L-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PCIE1L-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_MPCIEA429) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_MPCIEA429, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT MPCIE-A429 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT MPCIE-A429 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PMCMA4) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMCMA4, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PMC-MA4 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PMC-MA4 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
	    	else if (boardType == ADT_DEVID_BOARDTYPE_PC104EMA4) {
	    		if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PC104EMA4, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
	    		{
	    			logMsg("ADT PC104E-MA4 found.\n", 0,0,0,0,0,0);
	    			result = ADT_SUCCESS;
	    		}
	    		else
	    		{
	    			logMsg("ADT PC104E-MA4 NOT FOUND!\n", 0,0,0,0,0,0);
	    			result = ADT_ERR_NO_DEVICE;
	    		}
	    	}
			else if (boardType == ADT_DEVID_BOARDTYPE_XMCMA4) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_XMCMA4, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT XMC-MA4 found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT XMC-MA4 NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else if (boardType == ADT_DEVID_BOARDTYPE_PMCWMUX) {
				if (pciFindDevice(ADT_PCI_VENDOR_ID, ADT_PCI_DEVICE_ID_PMCWMUX, instance, (int *)&pciBus, (int *)&pciDevice, (int *)&pciFunc) == OK)
				{
					logMsg("ADT PMC-WMUX found.\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("ADT PMC-WMUX NOT FOUND!\n", 0,0,0,0,0,0);
					result = ADT_ERR_NO_DEVICE;
				}
			}
			else {
				result = ADT_ERR_UNSUPPORTED_BOARDTYPE;
			}

			/* Get the memory mapped base addresses for BAR0 and BAR2 */
			/* THIS IS USUALLY THE KEY AREA FOR DIFFERENT VXWORKS SYSTEMS/BSPs */
			if (result == ADT_SUCCESS) {
				pciConfigInLong(*pciBus, *pciDevice, *pciFunc, PCI_CFG_BASE_ADDRESS_0, &membase0);
				pciConfigInLong(*pciBus, *pciDevice, *pciFunc, PCI_CFG_BASE_ADDRESS_2, &membase2);
			/* This memoryBase assignments can change with different systems - see VxWorks_readme.txt */
				memoryBase0[backplaneType >> 28][boardType >> 20][boardNum >> 16] = membase0;
				memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16] = membase2;

			/* Get Interrupt line on the Client PCI card */
   			pciConfigInByte(*pciBus, *pciDevice, *pciFunc,
					PCI_CFG_DEV_INT_LINE, 		/* offset into the configuration space */
					&intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16]);  /* data read from the offset */
									

			}
			/*************************************************************************/
			break;


		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
		}
	}

	if (result == ADT_SUCCESS) {
		channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16]++;

		/* Perform the appropriate action to enable interrupts base on board type */
		switch (boardType) {
			/* PCI Devices with PLX 9056 */
			case ADT_DEVID_BOARDTYPE_PMC1553:
			case ADT_DEVID_BOARDTYPE_PC104P1553:
			case ADT_DEVID_BOARDTYPE_PCI1553:
			case ADT_DEVID_BOARDTYPE_TESTA429:
			case ADT_DEVID_BOARDTYPE_PMCA429:
			case ADT_DEVID_BOARDTYPE_PC104PA429:
			case ADT_DEVID_BOARDTYPE_PCIA429:
			case ADT_DEVID_BOARDTYPE_PMCMA4:
			case ADT_DEVID_BOARDTYPE_PMCWMUX:
			/* PCIe Devices */
			case ADT_DEVID_BOARDTYPE_PCI104E1553:
			case ADT_DEVID_BOARDTYPE_XMC1553:
			case ADT_DEVID_BOARDTYPE_ECD54_1553:
			case ADT_DEVID_BOARDTYPE_PCIE4L1553:
			case ADT_DEVID_BOARDTYPE_PCIE1L1553:
			case ADT_DEVID_BOARDTYPE_MPCIE1553:
			case ADT_DEVID_BOARDTYPE_PCI104EA429:
			case ADT_DEVID_BOARDTYPE_XMCA429:
			case ADT_DEVID_BOARDTYPE_ECD54_A429:
			case ADT_DEVID_BOARDTYPE_PCIE4LA429:
			case ADT_DEVID_BOARDTYPE_PCIE1LA429:
			case ADT_DEVID_BOARDTYPE_MPCIEA429:
			case ADT_DEVID_BOARDTYPE_PC104EMA4:
			case ADT_DEVID_BOARDTYPE_XMCMA4:
				/* Enable interrupt in PLX9056 */
				temp = 0;
				result = ADT_L0_ReadSetupMem32(devID, PLX_M_INTCSR, &temp, 1);
				temp |= BIT11 | BIT18;
				result = ADT_L0_WriteSetupMem32(devID, PLX_M_INTCSR, &temp, 1);

				/* Clear the compliance bit in the PLX9056 to enable "Direct Slave Retry Delay Clocks"
				   feature.  A PCI Retry will not be issued until after 32 PCI clocks (9056 default) 
				   from the beginning of a Direct Slave Read Access */
				temp = 0;
				result = ADT_L0_ReadSetupMem32(devID, PLX_M_MARBR, &temp, 1);
				temp &= ~0x01000000;
				result = ADT_L0_WriteSetupMem32(devID, PLX_M_MARBR, &temp, 1);

				/* Write to BAR0 memory and PLX offsets */
	            /* Use common settings for chain and direct DMA */
				u32DMAMODE = BIT6  /* Enable Ready input */
#if 0
				|    BIT10         /* Interrupt Enable */
	            |    BIT17         /* Interrupt Select */
#endif
	            |   (BIT1 | BIT0); /* 32-bit */
				ADT_L0_WriteSetupMem32(devID,PLX_M_DMAMODE0, &u32DMAMODE, 1); /*offset 0x80*/

				temp = (UINT32)0x8;/* Force direction to read from local bus */	
				ADT_L0_WriteSetupMem32(devID,PLX_M_DMADPR0, &temp, 1);/* offset 0x90 */

				/* Set DMA Big-Endian data for PPC */
				temp = BIT7;
				ADT_L0_WriteSetupMem32(devID,PLX_M_BIGEND, &temp, 1);/* offset 0x0C */
				break;

			default:
				break;
		}
	}
	return( result );
}

/******************************************************************************
  FUNCTION:		ADT_L0_UnmapMemory
 *****************************************************************************/
/*! \brief Unmaps memory
 *
 * This function un-maps and releases a previously mapped block of memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_UnmapMemory(ADT_L0_UINT32 devID) {
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_ENET_NODE *pENET_Node = NULL;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16]--;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
			/* Only close the WinDriver device if all channels for this board have been closed. */
			if (channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16] == 0)
			{
				/***** ADD VXWORKS MEM UNMAP CODE HERE *****/
				memoryBase0[backplaneType >> 28][boardType >> 20][boardNum >> 16] = 0;
				memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16] = 0;
			}

			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			free( (void *) SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] );
			SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] = NULL;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			/* Find the ENET Device Information node for the DEVID */
			pENET_Node = ADT_L0_Internal_Find_ENET_Node(devID);
			if (pENET_Node != NULL)
			{
				close(pENET_Node->eNET_Socket);
				pENET_Node->eNET_Socket = (SOCKET) NULL;
				ADT_L0_Internal_Destroy_ENET_Node(devID);

				if (channelInitCount[backplaneType >> 28][boardType >> 20][boardNum >> 16] == 0)
				{
					eNET_count--;
					if ((eNET_isRunning) && (eNET_count == 0))
						result = ADT_L0_Internal_eNet_Stop();
				}
			}
			else result = ADT_FAILURE;
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_ReadMem32
 *****************************************************************************/
/*! \brief Reads memory in 32-bit words
 * 
 * This function reads the requested number of 32-bit words from memory.
 * For the TEST-1553, this function accesses BAR-0 memory.
 * For the PMC-1553, this function accesses BAR-2 memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to read
 * @param data is a pointer to store the words read
 * @param count is the number of 32-bit words to read
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_DEV_NOT_INITED - Device not initialized
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ReadMem32(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT32 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT32 *memory;
    ADT_L0_UINT32 buf; 
    static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =	devID & 0x0FF00000;
	boardNum =	devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
			/* Read from BAR2 memory */
			memory = (ADT_L0_UINT32 *) memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16];
                        for (i=0; i<count; i++) {
                            buf = memory[offset/4 + i];  /* copy to local memory */
                            data[i] = BS32(buf);
                        }

			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			if (SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] != NULL) {
				for (i=0; i<count; i++) {
					data[i] = SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][offset/4 + i];
				}
			}
			else result = ADT_ERR_DEV_NOT_INITED;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_RD_MM_32;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			command.device_mem_addr = offset;
			command.transfer_count = count * 4;
			command.payload_size = 0;
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
			if (result == ADT_SUCCESS)
			{
				for (i=0; i<count; i++) data[i] = response.payload[i];
			}
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_ReadMem32DMA
 *****************************************************************************/
/*! \brief Reads memory in 32-bit words using DMA
 * 
 * This function reads the requested number of 32-bit words from memory.
 * For the TEST-1553, this function accesses BAR-0 memory.
 * For the PMC-1553, this function accesses BAR-2 memory.
 *
 * THIS FUNCTION IS NOT SUPPORTED FOR VXWORKS (Windows and Linux ONLY).
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to read
 * @param data is a pointer to store the words read
 * @param count is the number of 32-bit words to read
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_DEV_NOT_INITED - Device not initialized
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ReadMem32DMA(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT32 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS, temp;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT32 bufferAddr; 
    struct timespec rqtp;
    struct timespec rmtp;
	void *pMyBuf;
	void *pPhysAddr;
	
    rqtp.tv_sec = (time_t)0;
    rqtp.tv_nsec = (long) (20) * 1000000; 

    /* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

    /* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType)
	{
		case ADT_DEVID_BACKPLANETYPE_PCI:
#ifdef ADT_O2_PCMCIA_FIX
			result = ADT_L0_WD_ReadMem32(devID, 0, &i);
#endif

			/* If this board type supports DMA (PLX 9056) . . . */
			switch (boardType) {
				/* PCI Devices with PLX 9056 */
				case ADT_DEVID_BOARDTYPE_PMC1553:
				case ADT_DEVID_BOARDTYPE_PC104P1553:
				case ADT_DEVID_BOARDTYPE_PCI1553:
				case ADT_DEVID_BOARDTYPE_PMCA429:
				case ADT_DEVID_BOARDTYPE_PC104PA429:
				case ADT_DEVID_BOARDTYPE_PCIA429:
				case ADT_DEVID_BOARDTYPE_PMCMA4:
				case ADT_DEVID_BOARDTYPE_PC104PMA4:
				/* PCIe Devices */
				case ADT_DEVID_BOARDTYPE_PCI104E1553:
				case ADT_DEVID_BOARDTYPE_XMC1553:
				case ADT_DEVID_BOARDTYPE_ECD54_1553:
				case ADT_DEVID_BOARDTYPE_PCIE4L1553:
				case ADT_DEVID_BOARDTYPE_PCIE1L1553:
				case ADT_DEVID_BOARDTYPE_MPCIE1553:
				case ADT_DEVID_BOARDTYPE_PCI104EA429:
				case ADT_DEVID_BOARDTYPE_XMCA429:
				case ADT_DEVID_BOARDTYPE_ECD54_A429:
				case ADT_DEVID_BOARDTYPE_PCIE4LA429:
				case ADT_DEVID_BOARDTYPE_PCIE1LA429:
				case ADT_DEVID_BOARDTYPE_MPCIEA429:
				case ADT_DEVID_BOARDTYPE_PC104EMA4:
				case ADT_DEVID_BOARDTYPE_XMCMA4:
					
					/*Allocate*/
					/* allocate cache safe buffers if possible */
					if ((pMyBuf = cacheDmaMalloc (count*4)) == NULL)
						result = ADT_ERR_CACHEDMAFAIL;
						
					/* flush cache entry before data is written to device */
					CACHE_DMA_FLUSH (pMyBuf, count*4);

					/* convert virtual address to physical */
					pPhysAddr = CACHE_DMA_VIRT_TO_PHYS (pMyBuf);
					
			        bufferAddr = (unsigned int)pPhysAddr;

			        /* Then do the DMA read */
					/*Write count in bytes*/
			        temp = count*4;
					ADT_L0_WriteSetupMem32(devID,PLX_M_DMASIZ0, &temp, 1); /*offset 0x8C*/

					/*Write destination address*/
					ADT_L0_WriteSetupMem32(devID,PLX_M_DMAPADR0, &bufferAddr, 1); /*offset 0x84*/

					/*Write source address*/
					ADT_L0_WriteSetupMem32(devID,PLX_M_DMALADR0, &offset, 1); /*offset 0x88*/

			        taskLock();
					temp = BIT0 | BIT1; /* Enable Channel and start DMA*/
					ADT_L0_WriteSetupMem32(devID,PLX_M_DMACSR0, &temp, 1);

					 /* poll PLX dma done bit and wait for complete. */
			         do{
			        	 ADT_L0_ReadSetupMem32(devID,PLX_M_DMACSR0, &temp, 1);
			        	 /* Use "nanosleep" on VxWorks 5.x.  MAY NEED TO CHANGE FOR YOUR BSP. */
			        	 /* nanosleep (&rqtp, 0); */

			        	 /* Use "clock_nanosleep" on VxWorks 6.x.  MAY NEED TO CHANGE FOR YOUR BSP. */
			        	 clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &rqtp, &rmtp);
			         }while(!(temp & 0x00000010));
			         taskUnlock();

					/* convert physical to virtual address */
					pMyBuf = CACHE_DMA_PHYS_TO_VIRT (pPhysAddr);
					/* invalidate buffer */
					CACHE_DMA_INVALIDATE (pMyBuf, count*4);					
					 
					memcpy(data, pMyBuf, count*4);

					cacheDmaFree(pMyBuf);
					break;

				default:
					result = ADT_ERR_UNSUPPORTED_BOARDTYPE;
					break;
			}

			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			if (SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] != NULL) {
				for (i=0; i<count; i++) {
					data[i] = SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][offset/4 + i];
				}
			}
			else result = ADT_ERR_DEV_NOT_INITED;
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );

}


/******************************************************************************
  FUNCTION:		ADT_L0_WriteMem32
 *****************************************************************************/
/*! \brief Writes memory in 32-bit words 
 *
 * This function writes the requested number of 32-bit words to memory.
 * For the TEST-1553, this function accesses BAR-0 memory.
 * For the PMC-1553, this function accesses BAR-2 memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to write
 * @param data is a pointer to the words to write
 * @param count is the number of 32-bit words to write
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_DEV_NOT_INITED - Device not initialized
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_WriteMem32(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT32 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT32 *memory;
    ADT_L0_UINT32 buf; 
    static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =	devID & 0x0FF00000;
	boardNum =	devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
                        /* Write to BAR2 memory */
                        memory = (ADT_L0_UINT32 *) memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16];
                        for (i=0; i<count; i++) {
                            buf = BS32(data[i]);
                            memory[offset/4 + i] = buf;
                        } 

			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			if (SimDevMemory[boardNum >> 16][channelType >> 8][channelNum] != NULL) {
				for (i=0; i<count; i++) {
					SimDevMemory[boardNum >> 16][channelType >> 8][channelNum][offset/4 + i] = data[i];
				}
			}
			else result = ADT_ERR_DEV_NOT_INITED;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_WR_MM_32;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			command.device_mem_addr = offset;
			command.transfer_count = count * 4;
			command.payload_size = count * 4;
			for (i=0; i<count; i++) {
				command.payload[i] = data[i];
			}
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_ReadSetupMem32
 *****************************************************************************/
/*! \brief Reads the board setup memory in 32-bit words
 * 
 * This function reads the requested number of 32-bit words from board setup memory.
 * For the TEST-1553, this function is NOT SUPPORTED.
 * For the PMC-1553, this function accesses BAR-0 memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to read
 * @param data is a pointer to store the words read
 * @param count is the number of 32-bit words to read
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ReadSetupMem32(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT32 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT32 *memory;
    ADT_L0_UINT32 buf;
	static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =	devID & 0x0FF00000;
	boardNum =	devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
			/* Read from BAR0 memory */
			memory = (ADT_L0_UINT32 *) memoryBase0[backplaneType >> 28][boardType >> 20][boardNum >> 16];
                        for (i=0; i<count; i++) {
                            buf = memory[offset/4 + i];
                            data[i] = BS32(buf);
			}
			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_RD_SM_32;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			command.device_mem_addr = offset;
			command.transfer_count = count * 4;
			command.payload_size = 0;
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
			if (result == ADT_SUCCESS)
			{
				for (i=0; i<count; i++) data[i] = response.payload[i];
			}
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_WriteSetupMem32
 *****************************************************************************/
/*! \brief Writes the board setup memory in 32-bit words 
 *
 * This function writes the requested number of 32-bit words to board setup memory.
 * For the TEST-1553, this function is NOT SUPPORTED.
 * For the PMC-1553, this function accesses BAR-0 memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to write
 * @param data is a pointer to the words to write
 * @param count is the number of 32-bit words to write
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_WriteSetupMem32(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT32 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT32 *memory;
    ADT_L0_UINT32 buf;
	static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =	devID & 0x0FF00000;
	boardNum =	devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
                        /* Write to BAR0 memory */
                        memory = (ADT_L0_UINT32 *) memoryBase0[backplaneType >> 28][boardType >> 20][boardNum >> 16];
                        for (i=0; i<count; i++) {
                            buf = BS32(data[i]);
                            memory[offset/4 + i] = buf;
                        }
     
			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_WR_SM_32;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			command.device_mem_addr = offset;
			command.transfer_count = count * 4;
			command.payload_size = count * 4;
			for (i=0; i<count; i++) {
				command.payload[i] = data[i];
			}
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_ReadMem16
 *****************************************************************************/
/*! \brief Reads memory in 16-bit words
 * 
 * This function reads the requested number of 16-bit words from memory.
 * For the TEST-1553, this function accesses BAR-0 memory.
 * For the PMC-1553, this function accesses BAR-2 memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to read
 * @param data is a pointer to store the words read
 * @param count is the number of 16-bit words to read
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_DEV_NOT_INITED - Device not initialized
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ReadMem16(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT16 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT16 *memory;
    ADT_L0_UINT16 buf;
	static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
			/* Read from BAR2 memory */
			memory = (ADT_L0_UINT16 *) memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16];
			for (i=0; i<count; i++) {
                                buf = memory[offset/2 + i];
				data[i] = BS16(buf);
			}
			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			/* MAY NEED TO MODIFY THIS TO HANDLE 16-BIT WORDS - CHECK THIS!!! */
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_RD_MM_16;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			command.device_mem_addr = offset;
			command.transfer_count = count * 4;
			command.payload_size = 0;
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
			if (result == ADT_SUCCESS)
			{
				for (i=0; i<count; i++) data[i] = response.payload[i];
			}
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_WriteMem16
 *****************************************************************************/
/*! \brief Writes memory in 16-bit words 
 *
 * This function writes the requested number of 16-bit words to memory.
 * For the TEST-1553, this function accesses BAR-0 memory.
 * For the PMC-1553, this function accesses BAR-2 memory.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param offset is the BYTE offset to the first word to write
 * @param data is a pointer to the words to write
 * @param count is the number of 16-bit words to write
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_DEV_NOT_INITED - Device not initialized
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_WriteMem16(ADT_L0_UINT32 devID, ADT_L0_UINT32 offset, ADT_L0_UINT16 *data, ADT_L0_UINT32 count) {
	ADT_L0_UINT32 i;
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
	ADT_L0_UINT16 *memory;
    ADT_L0_UINT16 buf;
	static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* Perform the appropriate action based on BACKPLANE TYPE */
	switch (backplaneType) {
		case ADT_DEVID_BACKPLANETYPE_PCI:
			/* Write to BAR2 memory */
			memory = (ADT_L0_UINT16 *) memoryBase2[backplaneType >> 28][boardType >> 20][boardNum >> 16];
			for (i=0; i<count; i++) {
                                buf = BS16(data[i]);
				memory[offset/2 + i] = buf;
			}
			break;

		case ADT_DEVID_BACKPLANETYPE_SIMULATED:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;

		case ADT_DEVID_BACKPLANETYPE_ENET:
			/* MAY NEED TO MODIFY THIS TO HANDLE 16-BIT WORDS - CHECK THIS!!! */
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_WR_MM_16;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			command.device_mem_addr = offset;
			command.transfer_count = count * 4;
			command.payload_size = count * 4;
			for (i=0; i<count; i++) {
				command.payload[i] = data[i];
			}
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
			break;

		default:
			result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			break;
	}

	return( result );
}


/******************************************************************************
  INTERNAL FUNCTION:		ADT_L0_IntHandler
 *****************************************************************************/
/*! \brief Internal interrupt handler. 
 *
 * This is the interrupt handler function.  This function clears all interrupts
 * from devices in the linked-list of interrupt-enabled devices and calls
 * the appropriate user interrupt-handler functions.
 *
 * NOTE: The parameter pData is not used.  This is only here because that is 
 *       what the Jungo WinDriver software expects for interrupt handler 
 *       functions.
 */
void ADT_L0_CALL_CONV ADT_L0_IntHandler(void *pData) {
	ADT_L0_UINT32 status = ADT_SUCCESS;
	ADT_L0_UINT32 temp, temp2;
	ADT_INT_NODE *pIntNode;
	ADT_L0_PUSERISR ptr2function;

	/* Traverse the linked-list of interrupt-enabled devices.
	 *   - Clear interrupts and check interrupt-pending bits.
	 *   - If interrupt pending, call user interrupt-handler function.
	 */
	pIntNode = pHead_IntList;
	while (pIntNode != NULL)
	{
        ADT_Intr_cnt++;
		/* Check the interrupt pending bit in the PE STATUS REGISTER (bit 0) */
		status = ADT_L0_ReadMem32(pIntNode->DevID, pIntNode->ChanRegOffset + 0x00000004, &temp, 1);
		if(temp & 0x00000001) {

			/* Clear the pending bit */
			temp = 0;
			/* status = ADT_L0_WriteMem32(pIntNode->DevID, pIntNode->ChanRegOffset + 0x000000E0, &temp, 1); */
            status = ADT_L0_WriteMem32(pIntNode->DevID, pIntNode->ChanRegOffset + 0x00000004, &temp, 1);

			/* Call the user interrupt-handler function */
			ptr2function = pIntNode->pUser_Function;
			ptr2function(pIntNode->pUserData);
		}
		/*Check DMA Interrupt pending*/
		temp  = 0;
		temp2 = 0;
		status = ADT_L0_ReadSetupMem32(pIntNode->DevID,PLX_M_INTCSR, &temp, 1);
		if(temp & BIT21)
		{
			ADT_DMA_Intr++;
			temp2 = BIT3;
			status = ADT_L0_WriteSetupMem32(pIntNode->DevID,PLX_M_DMACSR0, &temp2, 1);

			/* Call the user interrupt-handler function */
			ptr2function = pIntNode->pUser_Function;
			ptr2function(pIntNode->pUserData);
		}
		
		/* Move to the next node */
		pIntNode = pIntNode->pNext;
	}
}



/******************************************************************************
  FUNCTION:		ADT_L0_AttachIntHandler
 *****************************************************************************/
/*! \brief Attaches a user interrupt handler function 
 *
 * This function attaches a user interrupt handler function.  The API creates
 * a node in the linked-list of interrupt-enabled devices and enables the
 * driver to call the internal interrupt handler (ADT_L0_IntHandler).
 *
 * @param devID is the 32-bit Device Identifier.
 * @param pUserISR is a pointer to the user function to attach.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Unsupported backplane
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_AttachIntHandler(ADT_L0_UINT32 devID, ADT_L0_UINT32 chanRegOffset, ADT_L0_PUSERISR pUserISR, void * pUserData) {
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_INT_NODE *pIntNode;
	ADT_INT_NODE *pNewIntNode;
	ADT_L0_UINT32 exists;
	ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;
   VOIDFUNCPTR* pIRQ;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =	devID & 0x0FF00000;
	boardNum =	devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;

	/* First check to make sure we don't already have a node for this device */
	exists = 0;
	pIntNode = pHead_IntList;
	while ((pIntNode != NULL) && (exists = 0)) 
	{
		if (pIntNode->DevID == devID) exists = 1;
		pIntNode = pIntNode->pNext;
	}

	/* If we don't already have a node for this device . . . */
	if (!exists) 
	{
		/* Create a new node */
		pNewIntNode = malloc(sizeof(ADT_INT_NODE));
		pNewIntNode->DevID = devID;
		pNewIntNode->ChanRegOffset = chanRegOffset;
		pNewIntNode->pUser_Function = pUserISR;
		pNewIntNode->pUserData = pUserData;
		pNewIntNode->pNext = NULL;

		/* Link the new node into the list */
		if (pHead_IntList == NULL) {
			pHead_IntList = pNewIntNode;
		}
		else {
			/* Find the end of the list */
			pIntNode = pHead_IntList;
			while (pIntNode->pNext != NULL) pIntNode = pIntNode->pNext;

			/* Add the new node */
			pIntNode->pNext = pNewIntNode;
		}

		/* Perform the appropriate action based on BACKPLANE TYPE */
		switch (backplaneType) {
			case ADT_DEVID_BACKPLANETYPE_PCI:
				/* Map intLine to our ISR */
#ifdef X86_PLATFORM
/*				pIRQ= INUM_TO_IVEC( (int) intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16] + 0x20);*/  /* GDR - was pIRQ=INUM_TO_IVEC((int)intLine); */
				/* The +0x20 is for x86 only */
				pIRQ= INUM_TO_IVEC( sysInumTbl[(int)intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16]]);  /* Modified for XES Xcalibur4440 */
#else
				pIRQ= INUM_TO_IVEC( (int) intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16]);
#endif
				result = intConnect(pIRQ,(void*)ADT_L0_IntHandler, channelNum); /* initial channel number '0' as the param*/
				/* Some BSPs do the int connect this way:
				result = pciIntConnect(pIRQ,(void*)ADT_L0_IntHandler, 0);
				*/

    			if (result == OK)
				{
					logMsg("Alta Int Handler connected\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
				}
				else
				{
					logMsg("Failure attaching int handler!\n", 0,0,0,0,0,0);
					result = ADT_FAILURE;
				}
				/* Enable the interrupt line. 
				   NOTE: THIS CALL MAY NEED TO CHANGE FOR THE SPECIFIC BSP BEING USED.
				         The sysIntEnablePIC call is used for VxWorks 5.5 on AMPRO Core Module 800 (Pentium M).
				*/

 				result = intEnable((int) intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16]); 
    			if (result == OK)
    			{
					logMsg("Alta int line enabled\n", 0,0,0,0,0,0);
					result = ADT_SUCCESS;
    			}
    			else
    			{
					logMsg("Failure enabling int line! %x (%d)\n", 
                           intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16],
						   result,
                           0,0,0,0);
					result = ADT_FAILURE;
    			}
                break;

			default:
				result = ADT_ERR_UNSUPPORTED_BACKPLANE;
				break;
		}
	}

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_DetachIntHandler
 *****************************************************************************/
/*! \brief Detaches an interrupt handler function 
 *
 * This function detaches an interrupt handler function.
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_DetachIntHandler(ADT_L0_UINT32 devID) {
   ADT_L0_UINT32 result = ADT_SUCCESS;
   ADT_INT_NODE *pIntNode;
   ADT_INT_NODE *pLastIntNode;
   ADT_L0_UINT32 exists;
   ADT_L0_UINT32 backplaneType, boardType, boardNum, channelType, channelNum;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	boardType =		devID & 0x0FF00000;
	boardNum =		devID & 0x000F0000;
	channelType =	devID & 0x0000FF00;
	channelNum =	devID & 0x000000FF;


	/* First check to make sure have a node for this device */
	exists = 0;
	pLastIntNode = NULL;
	pIntNode = pHead_IntList;

	while ((pIntNode != NULL) && (exists == 0)) 
	{
		if (pIntNode->DevID == devID) exists = 1;
		if (!exists) {
			pLastIntNode = pIntNode;
			pIntNode = pIntNode->pNext;
		}
	}

	if (exists) 
	{
		/* Remove node from the list */
		if (pLastIntNode == NULL) {
			pHead_IntList = pIntNode->pNext;
		}
		else {
			pLastIntNode->pNext = pIntNode->pNext;
		}
		
		/* Perform the appropriate action based on BACKPLANE TYPE */
		switch (backplaneType) {
		   case ADT_DEVID_BACKPLANETYPE_PCI:
		   /***** ADD VXWORKS CODE HERE TO DETACH THE HANDLER *****/
			 result = intDisable((int) intLine[backplaneType >> 28][boardType >> 20][boardNum >> 16]); 
 			 if (result != OK)
			 {
				logMsg("Failure Disabling int! %d\n", result,0,0,0,0,0);
				result = ADT_FAILURE;
			 }
		     break;

		   default:
			 result = ADT_ERR_UNSUPPORTED_BACKPLANE;
			 break;
			}
		free(pIntNode);
	}

	return( result );
}



/******************************************************************************
  FUNCTION:		ADT_L0_ENET_ADCP_GetStatistics
 *****************************************************************************/
/*! \brief Gets transaction and error counts for an ENET device
 *
 * This function gets the transaction and error counts for an ENET device.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param pPortNum is a pointer to store the UDP port number.
 * @param pTransactions is a pointer to store the transaction count.
 * @param pRetries is a pointer to store the error count.
 * @param pFailures is a pointer to store the failure count.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Not an ENET device
	- \ref ADT_ERR_ENET_NOTRUNNING - No ENET devices have been initialized
*/
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ENET_ADCP_GetStatistics(ADT_L0_UINT32 devID, ADT_L0_UINT32 *pPortNum, ADT_L0_UINT32 *pTransactions, ADT_L0_UINT32 *pRetries, ADT_L0_UINT32 *pFailures)
{
	ADT_L0_UINT32 result = ADT_SUCCESS;

	ADT_L0_UINT32 backplaneType;
	ADT_ENET_NODE *pENET_Node = NULL;

	backplaneType = devID & 0xF0000000;

	if (backplaneType == ADT_DEVID_BACKPLANETYPE_ENET)
	{
		if (eNET_isRunning) 
		{
			pENET_Node = ADT_L0_Internal_Find_ENET_Node(devID);
			if (pENET_Node != NULL)
			{
				*pPortNum = (ADT_L0_UINT32) pENET_Node->eNET_ClientUdpPort;
				*pTransactions = pENET_Node->eNET_TransactionCount;
				*pRetries = pENET_Node->eNET_RetryCount;
				*pFailures = pENET_Node->eNET_FailureCount;
			}
			else result = ADT_FAILURE;
		}
		else result = ADT_ERR_ENET_NOTRUNNING;
	}
	else result = ADT_ERR_UNSUPPORTED_BACKPLANE;

	return( result );
}


/******************************************************************************
  FUNCTION:		ADT_L0_ENET_ADCP_ClearStatistics
 *****************************************************************************/
/*! \brief Clears transaction and error counts for an ENET device
 *
 * This function clears the transaction and error counts for an ENET device.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Not an ENET device
	- \ref ADT_ERR_ENET_NOTRUNNING - No ENET devices have been initialized
*/
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ENET_ADCP_ClearStatistics(ADT_L0_UINT32 devID)
{
	ADT_L0_UINT32 result = ADT_SUCCESS;

	ADT_L0_UINT32 backplaneType;
	ADT_ENET_NODE *pENET_Node = NULL;

	backplaneType = devID & 0xF0000000;

	if (backplaneType == ADT_DEVID_BACKPLANETYPE_ENET)
	{
		if (eNET_isRunning) 
		{
			pENET_Node = ADT_L0_Internal_Find_ENET_Node(devID);
			if (pENET_Node != NULL)
			{
				pENET_Node->eNET_TransactionCount = 0;
				pENET_Node->eNET_RetryCount = 0;
				pENET_Node->eNET_FailureCount = 0;
			}
			else result = ADT_FAILURE;
		}
		else result = ADT_ERR_ENET_NOTRUNNING;
	}
	else result = ADT_ERR_UNSUPPORTED_BACKPLANE;
	return( result );
}

/******************************************************************************
  FUNCTION:		ADT_L0_ENET_ADCP_Reset
 *****************************************************************************/
/*! \brief Resets the ENET device.
 *
 * This function resets the ENET device.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Not an ENET device
	- \ref ADT_ERR_UNSUPPORTED_CHANNELTYPE - Not a GLOBAL channel/device
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_ENET_ADCP_Reset(ADT_L0_UINT32 devID)
{
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType, channelType;
	static ADT_L0_ADCP_UDPPAYLOAD command, response;

	/* Break out the fields of the Device ID */
	backplaneType = devID & 0xF0000000;
	channelType =	devID & 0x0000FF00;

	if (backplaneType == ADT_DEVID_BACKPLANETYPE_ENET)
	{
		if (channelType == ADT_DEVID_CHANNELTYPE_GLOBALS)
		{
			memset(&command, 0, sizeof(command));  memset(&response, 0, sizeof(response));
			command.mode = ADT_L0_ENET_ADCP_HDR_MODE_RESETDEV;
			command.altastring = ADT_L0_ENET_ADCP_HDR_ALTASTRING_VAL;
			result = ADT_L0_Internal_eNet_ADCP_Execute(devID, &command, &response);
		}
		else result = ADT_ERR_UNSUPPORTED_CHANNELTYPE;
	}
	else result = ADT_ERR_UNSUPPORTED_BACKPLANE;

	return( result );
}

/******************************************************************************
  FUNCTION:		ADT_L0_Internal_eNet_Start
 *****************************************************************************/
/*! \brief Starts ENET services for UDP sockets.
 *
 * This function starts ENET services for UDP sockets.
 *
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_Internal_eNet_Start()
{
	ADT_L0_UINT32 result = ADT_SUCCESS;

	if (result == ADT_SUCCESS) eNET_isRunning = 1;
	return( result );
}

/******************************************************************************
  FUNCTION:		ADT_L0_Internal_eNet_Stop
 *****************************************************************************/
/*! \brief Stops ENET services for UDP sockets.
 *
 * This function stops ENET services for UDP sockets.
 *
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_Internal_eNet_Stop()
{
	ADT_L0_UINT32 result = ADT_SUCCESS;

	eNET_isRunning = 0;
	return( result );
}

/******************************************************************************
  FUNCTION:		ADT_L0_Internal_eNet_ADCP_Execute
 *****************************************************************************/
/*! \brief Executes an ADCP operation.
 *
 * This function executes an ADCP operation with UDP handshake.
 *
 * @param devID is the 32-bit Device Identifier.
 * @param command is the pointer to the command packet payload.
 * @param response is the pointer to the response packet payload.
 * @return 
	- \ref ADT_SUCCESS - Completed without error
	- \ref ADT_FAILURE - Completed with error
	- \ref ADT_ERR_ENET_NOTRUNNING - Socket services are not running
	- \ref ADT_ERR_UNSUPPORTED_BACKPLANE - Backplane type is not ENET
	- \ref ADT_ERR_ENET_INVALID_SIZE - ADCP payload size exceeds maximum
	- \ref ADT_ERR_ENET_SENDFAIL - sendto call failed
 */
ADT_L0_UINT32 ADT_L0_CALL_CONV ADT_L0_Internal_eNet_ADCP_Execute(ADT_L0_UINT32 devID, ADT_L0_ADCP_UDPPAYLOAD *command, ADT_L0_ADCP_UDPPAYLOAD *response)
{
	ADT_L0_UINT32 result = ADT_SUCCESS;
	ADT_L0_UINT32 backplaneType;
	ADT_L0_UINT32 retryCount, goodResponseReceived, byteCount, payloadSize, i, respSeqNum, srvrStatus;
	char commandUdpPayload[ADT_L0_ENET_ADCP_UDPPAYLOAD_MAXSZ];
	char responseUdpPayload[ADT_L0_ENET_ADCP_UDPPAYLOAD_MAXSZ];
	struct sockaddr_in server_addr;
	fd_set socketReadSet;
	struct timeval tv;
	size_t addr_len;
	int rv;
	ADT_ENET_NODE *pENET_Node = NULL;

	backplaneType = devID & 0xF0000000;

	if (backplaneType == ADT_DEVID_BACKPLANETYPE_ENET)
	{
		if (eNET_isRunning) 
		{
			/* Find the ENET Device Information node for the DEVID */
			pENET_Node = ADT_L0_Internal_Find_ENET_Node(devID);
			if (pENET_Node != NULL)
			{
				/*Take mutex*/
				semTake (pENET_Node->eNET_Mutex, WAIT_FOREVER);

				/* Increment the ENET Transaction Counter */
				pENET_Node->eNET_TransactionCount++;

				/* Increment the sequence number for the device */
				pENET_Node->eNET_SequenceNumber++;
				command->sequence_number = pENET_Node->eNET_SequenceNumber;

				/* Define the server address/port */
				server_addr.sin_family = AF_INET;
				server_addr.sin_port = htons(ADT_L0_ENET_ADCP_SERVER_PORT);
    			server_addr.sin_addr.s_addr = htonl(pENET_Node->eNET_ServerIPaddr);

				/* Build UDP payload for command packet */
				memset(commandUdpPayload, 0, sizeof(commandUdpPayload));
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_MODE]) = htonl(command->mode);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_SEQNUM]) = htonl(command->sequence_number);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_SRVSTS]) = htonl(command->server_status_word);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_ALTASTRING]) = htonl(command->altastring);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_RSVD1]) = htonl(command->reserved_1);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_DEVMEMADDR]) = htonl(command->device_mem_addr);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_XFERCOUNT]) = htonl(command->transfer_count);
				*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_HDR_PAYLOADSZ]) = htonl(command->payload_size);
				payloadSize = command->payload_size;
				if (payloadSize <= ADT_L0_ENET_ADCP_ADCPPAYLOAD_MAXSZ)
				{
					for (i=0; i<payloadSize; i+=4)
					{
						*( (ADT_L0_UINT32 *) &commandUdpPayload[ADT_L0_ENET_ADCP_PAYLOAD + i]) = htonl(command->payload[i/4]);
					}

					/* Clear the receive buffer */
					FD_ZERO(&socketReadSet);
					FD_SET(pENET_Node->eNET_Socket, &socketReadSet);
					tv.tv_sec = 0;
					tv.tv_usec = 0;
					rv = 1;
					while (rv > 0)
					{
						rv = select((int)pENET_Node->eNET_Socket+1, &socketReadSet, NULL, NULL, &tv);
						if (rv > 0)  
						{
							addr_len = sizeof(server_addr);
							byteCount = recvfrom(pENET_Node->eNET_Socket, responseUdpPayload, ADT_L0_ENET_ADCP_UDPPAYLOAD_MAXSZ, 0, (struct sockaddr *) &server_addr, (int *) &addr_len);
						}
					}

					retryCount = ADT_L0_ENET_ADCP_MAXNUMRETRY;
					goodResponseReceived = 0;
					while ((retryCount > 0) && (!goodResponseReceived))
					{
						/* Send the command packet */
						byteCount = sendto(pENET_Node->eNET_Socket, commandUdpPayload, payloadSize + 32, 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr));
						
						if (byteCount == payloadSize + 32)
						{
							/* Receive the response packet */
							FD_ZERO(&socketReadSet);
							FD_SET(pENET_Node->eNET_Socket, &socketReadSet);
							tv.tv_sec = ADT_L0_ENET_ADCP_TIMEOUT_MS / 1000;
							tv.tv_usec = (ADT_L0_ENET_ADCP_TIMEOUT_MS - (tv.tv_sec * 1000)) * 1000;
							rv = select((int)pENET_Node->eNET_Socket+1, &socketReadSet, NULL, NULL, &tv);
							if (rv < 0) result = ADT_ERR_ENET_SELECTFAIL;
							else if (rv == 0) result = ADT_ERR_ENET_SELECTTIMEOUT;
							else {
								memset(responseUdpPayload, 0, sizeof(responseUdpPayload));
								addr_len = sizeof(server_addr);
								byteCount = recvfrom(pENET_Node->eNET_Socket, responseUdpPayload, ADT_L0_ENET_ADCP_UDPPAYLOAD_MAXSZ, 0, (struct sockaddr *) &server_addr, (int *) &addr_len);

								/* Verify the SEQUENCE NUMBER and SERVER STATUS WORD to determine if the response is valid */
								respSeqNum = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_SEQNUM]));
								srvrStatus = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_SRVSTS]));
								if (respSeqNum == command->sequence_number) {
									if ((srvrStatus & ADT_L0_ENET_ADCP_HDR_SRVSTS_CODE) == ADT_L0_ENET_ADCP_HDR_SRVSTS_SUCCESS) {
										goodResponseReceived = 1;
										result = ADT_SUCCESS;

										/* Copy response packet to structure (pass back to caller) */
										response->mode = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_MODE]));
										response->sequence_number = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_SEQNUM]));
										response->server_status_word = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_SRVSTS]));
										response->altastring = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_ALTASTRING]));
										response->reserved_1 = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_RSVD1]));
										response->device_mem_addr = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_DEVMEMADDR]));
										response->transfer_count = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_XFERCOUNT]));
										response->payload_size = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_HDR_PAYLOADSZ]));
										payloadSize = response->payload_size;
										if (payloadSize > ADT_L0_ENET_ADCP_ADCPPAYLOAD_MAXSZ) payloadSize = ADT_L0_ENET_ADCP_ADCPPAYLOAD_MAXSZ;
										for (i=0; i<payloadSize; i+=4)
										{
											response->payload[i/4] = ntohl(*( (ADT_L0_UINT32 *) &responseUdpPayload[ADT_L0_ENET_ADCP_PAYLOAD + i]));
										}
									}
									else result = ADT_ERR_ENET_SRVSTSFAIL;
								}
								else result = ADT_ERR_ENET_BADSEQNUM;
							}

							/* Decrement retry count */
							retryCount--;
						}
						else {
							retryCount = 0;
							result = ADT_ERR_ENET_SENDFAIL;
						}

						/* If any error increment the ENET Retry Counter */
						if (result != ADT_SUCCESS) pENET_Node->eNET_RetryCount++;

					}  /* End of WHILE loop (for retries) */
				}
				else result = ADT_ERR_ENET_INVALID_SIZE;

				/* Release the MUTEX */
				semGive(pENET_Node->eNET_Mutex);
			}
			else result = ADT_FAILURE;

			/* If any error at this point, then all retries failed, increment the ENET Failure Counter */
			if (result != ADT_SUCCESS) pENET_Node->eNET_FailureCount++;
		}
		else result = ADT_ERR_ENET_NOTRUNNING;
	}
	else result = ADT_ERR_UNSUPPORTED_BACKPLANE;

	return( result );
}



/******************************************************************************
  INTERNAL FUNCTION:		ADT_L0_Internal_Find_ENET_Node
 *****************************************************************************/
/*! \brief Finds an ENET device info node based on DEVID
 *
 * This function finds an ENET device info node based on DEVID.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref NULL - No matching node found
	- \ref Pointer to the node found
*/
ADT_ENET_NODE * ADT_L0_Internal_Find_ENET_Node(ADT_L0_UINT32 devID)
{
	ADT_ENET_NODE *pNode;
	ADT_L0_UINT32 found;

	pNode = pENET_Head;  found = 0;
	while ((!found) && (pNode != NULL)) {
		if (pNode->DevID == devID) found = 1;
		else pNode = pNode->pNext;
	}

	return( pNode );
}


/******************************************************************************
  INTERNAL FUNCTION:		ADT_L0_Internal_FindOrAdd_ENET_Node
 *****************************************************************************/
/*! \brief Finds/adds an ENET device info node based on DEVID
 *
 * This function finds/adds an ENET device info node based on DEVID.
 *
 * @param devID is the 32-bit Device Identifier.
 * @return 
	- \ref Pointer to the node found/added
*/
ADT_ENET_NODE * ADT_L0_Internal_FindOrAdd_ENET_Node(ADT_L0_UINT32 devID)
{
	ADT_ENET_NODE *pNode, *pTail;
	ADT_L0_UINT32 found;

	/* First check to see if a node already exists for the DEVID */
	pNode = pENET_Head;  pTail = NULL; found = 0;
	while ((!found) && (pNode != NULL)) {
		if (pNode->DevID == devID) found = 1;
		else {
			pTail = pNode;
			pNode = pNode->pNext;
		}
	}

	/* If no matching node found then create new one */
	if (pNode == NULL) {
		pNode = malloc(sizeof(ADT_ENET_NODE));
		if (pNode != NULL) {
			memset(pNode, 0, sizeof(ADT_ENET_NODE));
			pNode->DevID = devID;
			pNode->eNET_Socket = 0;

			/* Initialize mutex */
			pNode->eNET_Mutex = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
			pNode->pNext = NULL;

			if (pTail == NULL) pENET_Head = pNode;
			else pTail->pNext = pNode;
		}
	}

	return( pNode );
}


/******************************************************************************
  INTERNAL FUNCTION:		ADT_L0_Internal_Destroy_ENET_Node
 *****************************************************************************/
/*! \brief Frees an ENET device info node based on DEVID
 *
 * This function frees an ENET device info node based on DEVID.
 *
 * @param devID is the 32-bit Device Identifier.
*/
void ADT_L0_Internal_Destroy_ENET_Node(ADT_L0_UINT32 devID)
{
	ADT_ENET_NODE *pNode, *pLast;

	pNode = pENET_Head;
	pLast = pENET_Head;
	while (pNode != NULL) {
		if (pNode->DevID == devID) {
			pLast->pNext = pNode->pNext;
			if (pENET_Head == pNode) pENET_Head = pNode->pNext;
			free(pNode); pNode = NULL;
		}
		else {
			pLast = pNode;
			pNode = pNode->pNext;
		}
	}
}

#ifdef __cplusplus
}
#endif
